﻿using FySystem.Converter;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace FySystem.Net
{
    public class FyNetStream : MemoryStream
    {
        public enum FyStreamDataTypes
        {
            /// <summary>
            /// C#默认模式
            /// </summary>
            LittleEndian,
            /// <summary>
            /// 和小端相反
            /// </summary>
            BigEndian
        }

        public Socket client { get; set; }

        /// <summary>
        /// 流类型（大端还是小端）
        /// </summary>
        public FyStreamDataTypes StreamDataType { get; set; } = FyStreamDataTypes.LittleEndian;

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="dateType"></param>
        /// <param name="datas"></param>
        public FyNetStream(FyStreamDataTypes dataType, byte[] datas, int offset, int count)
        {
            StreamDataType = dataType;
            this.Write(datas, offset, count);
            this.Seek(0, SeekOrigin.Begin);
        }

        public FyNetStream(FyStreamDataTypes dataType, byte[] datas)
        {
            StreamDataType = dataType;
            this.Write(datas, 0, datas.Length);
            this.Seek(0, SeekOrigin.Begin);
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        public void SendData(byte[] data)
        {
            try
            {

            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 顺序读取单个字节
        /// </summary>
        /// <returns></returns>
        public byte GetByte()
        {
            byte[] res = new byte[1];
            try
            {
                res = this.GetBytes(1);
            }
            catch (Exception)
            {
                throw;
            }
            return res[0];
        }

        /// <summary>
        /// 读取指定长度的字节
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public byte[] GetBytes(int length)
        {
            byte[] res = new byte[length];
            try
            {
                this.Read(res, 0, length);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取两字节短整型
        /// </summary>
        /// <returns></returns>
        public short GetShort()
        {
            short res = -1;
            try
            {
                byte[] data = GetBytes(2);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToShort(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取两字节短整型，如果读取出来的值与forVal相同，则替换为destVal
        /// </summary>
        /// <param name="forVal"></param>
        /// <param name="destVal"></param>
        /// <returns></returns>
        public short GetShort(short forVal, short destVal)
        {
            short res = 0;
            try
            {
                res = GetShort();
                res = res == forVal ? destVal : res;
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取两字节无符号短整型
        /// </summary>
        /// <returns></returns>
        public ushort GetUShort()
        {
            ushort res = 0;
            try
            {
                byte[] data = GetBytes(2);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToUShort(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取两字节无符号短整型，如果读取出来的值与forVal相同，则替换为destVal
        /// </summary>
        /// <param name="forVal"></param>
        /// <param name="destVal"></param>
        /// <returns></returns>
        public ushort GetUShort(ushort forVal, ushort destVal)
        {
            ushort res = 0;
            try
            {
                res = GetUShort();
                res = res == forVal ? destVal : res;
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取四字节整型
        /// </summary>
        /// <returns></returns>
        public int GetInt()
        {
            int res = -1;
            try
            {
                byte[] data = GetBytes(4);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToInt(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取四字节整型
        /// </summary>
        /// <param name="forVal"></param>
        /// <param name="destVal"></param>
        /// <returns></returns>
        public int GetInt(int forVal, int destVal)
        {
            int res = 0;
            try
            {
                res = GetInt();
                res = res == forVal ? destVal : res;
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取无符号整型
        /// </summary>
        /// <returns></returns>
        public uint GetUInt()
        {
            UInt32 res = 0;
            try
            {
                byte[] data = GetBytes(4);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToUInt(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取无符号整型
        /// </summary>
        /// <param name="forVal"></param>
        /// <param name="destVal"></param>
        /// <returns></returns>
        public uint GetUInt(uint forVal, uint destVal)
        {
            UInt32 res = 0;
            try
            {
                byte[] data = GetBytes(4);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToUInt(data);
                res = res == forVal ? destVal : res;
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取长整型
        /// </summary>
        /// <returns></returns>
        public long GetLong()
        {
            long res = -1;
            try
            {
                byte[] data = GetBytes(8);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToLong(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取无符号长整型
        /// </summary>
        /// <returns></returns>
        public ulong GetULong()
        {
            ulong res = 0;
            try
            {
                byte[] data = GetBytes(8);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToULong(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 获取浮点
        /// </summary>
        /// <returns></returns>
        public float GetFloat()
        {
            float res = 0;
            try
            {
                byte[] data = GetBytes(4);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToFloat(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 读取指定长度的字节，并将其转换为十六进制字符串
        /// </summary>
        /// <param name="length"></param>
        /// <param name="whiteSpace"></param>
        /// <returns></returns>
        public string GetHexString(int length, bool whiteSpace)
        {
            string res = "";
            try
            {
                byte[] data = this.GetBytes(length);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    data = data.Reverse().ToArray();
                res = NumberConversion.BytesToHexString(data, 0, data.Length, whiteSpace);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 暂时不确定是否稳定
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public byte[] GetBinary(int length)
        {
            byte[] res = null;
            try
            {
                byte[] bytes = GetBytes(length);
                if (StreamDataType == FyStreamDataTypes.BigEndian)
                    bytes = bytes.Reverse().ToArray();
                res = NumberConversion.BytesToBinary(bytes);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 跳过指定长度的字节数
        /// </summary>
        /// <param name="length"></param>
        public void SkipBytes(int length)
        {
            try
            {
                //this.Seek(length, SeekOrigin.Current);
                byte[] buffer = new byte[length];
                this.Read(buffer, 0, buffer.Length);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public override string ToString()
        {
            //return base.ToString();
            return NumberConversion.BytesToHexString(this.ToArray(), 0, (int)this.Length, false);
        }

        protected override void Dispose(bool disposing)
        {
            try
            {
                if (client != null)
                {
                    client.Dispose();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            base.Dispose(disposing);
        }
    }
}
